import { resolve } from "node:path"
import grpc from "@grpc/grpc-js"
import { loadProto } from "../utils/loadProto.js"

function unaryEchoCall(client) {
  return new Promise((resolve, reject) => {
    client.unaryEcho({ name: "tom" }, (err, res) => {
      console.log("Client Received: ", res.value)
      resolve()
    })
  })
}

function serverStreamingEchoCall(client) {
  return new Promise((resolve) => {
    const call = client.serverStreamingEcho()
    let result = ""

    call.on("data", (data) => {
      result += data.value
    })

    call.on("status", (status) => {
      if (status.code === grpc.status.OK) {
        console.log(`Client Received: ${result}`)
        resolve()
      }
    })

    call.on("end", () => {
      console.log("Server Streaming end")
      resolve()
    })
  })
}

function clientStreamingEchoCall(client) {
  return new Promise((resolve) => {
    const call = client.clientStreamingEcho((err, res) => {
      console.log(res.value)
    })
    const params = "Client Param"

    for (let i = 0; i < params.length; i++) {
      call.write({ name: params[i] })
    }
    call.end()
    resolve()
  })
}

function bidirectionalStreamingEchoCall(client) {
  return new Promise((resolve) => {
    const call = client.bidirectionalStreamingEcho()

    call.on("data", (data) => {
      charCodes.push(data.value)
    })

    call.on("status", (status) => {
      if (grpc.status[status.code] === grpc.status.OK) {
        console.log(`Duplex Received: ${charCodes}`)
      }
    })

    call.on("end", () => {
      console.log("Duplex Streaming end ", charCodes)
    })

    const charCodes = []
    const hello_1 = "Hello From Duplex"

    for (let i = 0; i < hello_1.length; i++) {
      call.write({ name: hello_1[i] })
    }
    call.end()
    resolve()
  })
}

async function run() {
  const PROTO_PATH = resolve(process.cwd(), "./echo.proto")
  const echoProtoDescriptor = loadProto(PROTO_PATH)
  const echoProto = echoProtoDescriptor.echo
  const client = new echoProto.Echo(
    "localhost:50051",
    grpc.credentials.createInsecure()
  )

  await unaryEchoCall(client)
  console.log("==============================")
  await serverStreamingEchoCall(client)
  console.log("==============================")
  await clientStreamingEchoCall(client)
  console.log("==============================")
  await bidirectionalStreamingEchoCall(client)
}

run()
